// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "framework.h"

#include <unordered_map>
#include "DealShm.h"

std::unordered_map<const char*, int > func_type = {
    {"MessageBoxA", 1},
    {"MessageBoxW", 2},
    {"CreateFileA", 3 },
    {"WriteFile", 4 },
    {"ReadFile", 5 },
    {"OpenFile", 6 },
    {"HeapAlloc", 7 },
    {"HeapCreate", 8 },
    {"HeapDestory", 9 },
    {"HeapFree", 10 },
    {"RegCreateKeyExA", 11 },
    {"RegSetValueExA", 12 },
    {"RegCloseKey", 13 },
    {"RegOpenKeyExA", 14 },
    {"RegDeleteValueA", 15 },
    {"socket", 16 },
    {"bind", 17 },
    {"send", 18 },
    {"connect", 19 },
    {"memcpy", 20 },
    {"recv", 21 }
};

char outputStr[1000];               // 暂存调试信息
WCHAR outputWStr[1000];             // 暂存调试信息

// 共享内存相关
HANDLE hSemap;                      // 信号量句柄
WCHAR nameSemap[10] = L"dbgSemap";  // 信号量名称
HANDLE hMap;                        // 内存映射对象句柄
WCHAR nameShm[10] = L"dbgShm";      // 共享内存名称
LPVOID pShm;                        // 共享内存指针
int count = 0;                      // 当前操作的字符串编号
SHM* shm;                           // 函数信息结构体指针
std::mutex mtx[shm_num];            // 共享内存读写锁

// 定义和引入需要Hook的函数，和替换的函数


template<typename Tx, typename T2, typename Ty>
// 按格式写入变量dst[i]
void sprintfWithType(Tx dst, T2 i, Ty arg)
{
    if(typeid(arg)==typeid(LPCSTR))
    {
        sprintf_s(dst[i], "%s", AlterRN((LPCSTR)arg));        //AlterRN将文本中的特殊符号转换为原始字符
    }
    else if(typeid(arg) == typeid(LPCWSTR))
    {
        sprintf_s(dst[i], "%s", AlterRN((LPCWSTR)arg));        //AlterRN将文本中的特殊符号转换为原始字符
        
    }
    else if (typeid(arg) == typeid(int))
    {
        sprintf_s(dst[i], "%08d", (int)arg);
    }
    else {
        sprintf_s(dst[i], "%08X", (UINT32)arg);
    }
}
// 扩展使sprintfWithType函数可接收无穷多参数， 同时，返回接收的参数个数
template <typename Args1, typename ...Args2>
int sprintfWithTypeEx(Args1 args1, Args2... args2)
{
    int i = 1;
    int arr[] = { (sprintfWithType(args1, i++, args2), 0)... };
    return i-1;
}


// 1,2 弹窗 MessageBoxA MessageBoxW
decltype(MessageBoxA)* OldMessageBoxA = MessageBoxA;
decltype(MessageBoxW)* OldMessageBoxW = MessageBoxW;

extern "C" __declspec(dllexport) int WINAPI NewMessageBoxA(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "MessageBoxA";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hWnd, lpText, lpCaption, uType);
    // 参数名
    sprintf_s(info.argName[1], "hWnd");
    sprintf_s(info.argName[2], "lpText");
    sprintf_s(info.argName[3], "lpCaption");
    sprintf_s(info.argName[4], "uType");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    sprintf_s(outputStr, "new %s\nU201911729申珊靛", func_name);
    return OldMessageBoxA(NULL, outputStr, "Hooked", MB_OK);
}

extern "C" __declspec(dllexport) int WINAPI NewMessageBoxW(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText, _In_opt_ LPCWSTR lpCaption, _In_ UINT uType)
{    
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "MessageBoxW";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hWnd, lpText, lpCaption, uType);
    // 参数名
    sprintf_s(info.argName[1], "hWnd");
    sprintf_s(info.argName[2], "lpText");
    sprintf_s(info.argName[3], "lpCaption");
    sprintf_s(info.argName[4], "uType");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    swprintf_s(outputWStr, L"new %s\nU201911729申珊靛", func_name);
    return OldMessageBoxW(NULL, outputWStr, L"Hooked", MB_OK);
}


// 3,4,5,6 文件操作 CreateFileA WriteFile ReadFile OpenFile
decltype(CreateFileA)* OldCreateFileA = CreateFileA;
decltype(WriteFile)* OldWriteFile = WriteFile;
decltype(ReadFile)* OldReadFile = ReadFile;
decltype(OpenFile)* OldOpenFile = OpenFile;

extern "C" __declspec(dllexport) HANDLE WINAPI NewCreateFileA(
    LPCSTR lpFileName,
    DWORD dwDesiredAccess,
    DWORD dwShareMode,
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    DWORD dwCreationDisposition,
    DWORD dwFlagsAndAttributes,
    HANDLE hTemplateFile)
{
    HANDLE hFile = OldCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    if (GetFileType(hFile) == FILE_TYPE_DISK) {
        // 优先将所有的数据都存储成info，处理好，准备放入共享内存
        func_info info;                                                     // 函数信息结构体
        // 函数基础信息
        const char* func_name = "CreateFileA";                              // 函数名称
        OutputDebugStringA(func_name);
        sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
        sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
        // Hook时间戳
        GetLocalTime(&info.st);
        // 参数值格式化存入，并获取参数个数
        info.argNum = sprintfWithTypeEx(info.argValue, lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
        // 参数名
        sprintf_s(info.argName[1], "lpFileName");
        sprintf_s(info.argName[2], "dwDesiredAccess");
        sprintf_s(info.argName[3], "dwShareMode");
        sprintf_s(info.argName[4], "lpSecurityAttributes");
        sprintf_s(info.argName[5], "dwCreationDisposition");
        sprintf_s(info.argName[6], "dwFlagsAndAttributes");
        sprintf_s(info.argName[7], "hTemplateFile");
        // 共享内存管理
        if (UpdateShm(shm, count) != -1) {
        mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
        count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
        mtx[count].unlock();}
    }
    // 返回原始接口
    return hFile;
}

extern "C" __declspec(dllexport)BOOL WINAPI NewWriteFile(
    HANDLE       hFile,
    LPCVOID      lpBuffer,
    DWORD        nNumberOfBytesToWrite,
    LPDWORD      lpNumberOfBytesWritten,
    LPOVERLAPPED lpOverlapped
)
{
    if (GetFileType(hFile) == FILE_TYPE_DISK) {
        // 优先将所有的数据都存储成info，处理好，准备放入共享内存
        func_info info;                                                     // 函数信息结构体
        // 函数基础信息
        const char* func_name = "WriteFile";                              // 函数名称
        OutputDebugStringA(func_name);
        sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
        sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
        // Hook时间戳
        GetLocalTime(&info.st);
        // 参数值格式化存入，并获取参数个数
        info.argNum = sprintfWithTypeEx(info.argValue, hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
        // 参数名
        sprintf_s(info.argName[1], "hFile");
        sprintf_s(info.argName[2], "lpBuffer");
        sprintf_s(info.argName[3], "nNumberOfBytesToWrite");
        sprintf_s(info.argName[4], "lpNumberOfBytesWritten");
        sprintf_s(info.argName[5], "lpOverlapped");
        // 共享内存管理
        if (UpdateShm(shm, count) != -1) {
        mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
        count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
        mtx[count].unlock();}
    }
    return OldWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
}

extern "C" __declspec(dllexport) BOOL WINAPI NewReadFile(
    HANDLE hFile,
    LPVOID lpBuffer,
    DWORD nNumberOfBytesToRead,
    LPDWORD lpNumberOfBytesRead,
    LPOVERLAPPED lpOverlapped)
{
    if (GetFileType(hFile) == FILE_TYPE_DISK) {
        // 优先将所有的数据都存储成info，处理好，准备放入共享内存
        func_info info;                                                     // 函数信息结构体
        // 函数基础信息
        const char* func_name = "ReadFile";                              // 函数名称
        OutputDebugStringA(func_name);
        sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
        sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
        // Hook时间戳
        GetLocalTime(&info.st);
        // 参数值格式化存入，并获取参数个数
        info.argNum = sprintfWithTypeEx(info.argValue, hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
        // 参数名
        sprintf_s(info.argName[1], "hFile");
        sprintf_s(info.argName[2], "lpBuffer");
        sprintf_s(info.argName[3], "nNumberOfBytesToRead");
        sprintf_s(info.argName[4], "lpNumberOfBytesRead");
        sprintf_s(info.argName[5], "lpOverlapped");
        OutputDebugStringA("test1");
        // 共享内存管理
        if (UpdateShm(shm, count) != -1) {
        OutputDebugStringA("test2");
        sprintf_s(outputStr, "%d", count);
        OutputDebugStringA(outputStr);
        mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
        OutputDebugStringA("test3");
        count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
        OutputDebugStringA("test5");
        mtx[count].unlock();}
        OutputDebugStringA("test4");
    }
    // 返回原始接口
    return OldReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
}

extern "C" __declspec(dllexport) HFILE WINAPI NewOpenFile(
    _In_    LPCSTR lpFileName,
    _Inout_ LPOFSTRUCT lpReOpenBuff,
    _In_    UINT uStyle)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "OpenFile";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, lpFileName, lpReOpenBuff, uStyle);
    // 参数名
    sprintf_s(info.argName[1], "lpFileName");
    sprintf_s(info.argName[2], "lpReOpenBuff");
    sprintf_s(info.argName[3], "uStyle");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    return OldOpenFile(lpFileName, lpReOpenBuff, uStyle);
}


// 7,8,9,10 堆操作 HeapAlloc HeapCreate HeapDestory HeapFree
decltype(HeapAlloc)* OldHeapAlloc = HeapAlloc;
decltype(HeapCreate)* OldHeapCreate = HeapCreate;
decltype(HeapDestroy)* OldHeapDestory = HeapDestroy;
decltype(HeapFree)* OldHeapFree = HeapFree;

extern "C" __declspec(dllexport) LPVOID WINAPI NewHeapAlloc(
    _In_ HANDLE hHeap,
    _In_ DWORD dwFlags,
    _In_ SIZE_T dwBytes)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "HeapAlloc";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hHeap, dwFlags, dwBytes);
    // 参数名
    sprintf_s(info.argName[1], "hHeap");
    sprintf_s(info.argName[2], "dwFlags");
    sprintf_s(info.argName[3], "dwBytes");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    return OldHeapAlloc(hHeap, dwFlags, dwBytes);
}

extern "C" __declspec(dllexport) HANDLE WINAPI NewHeapCreate(
    DWORD fIOoptions,
    SIZE_T dwInitialSize,
    SIZE_T dwMaximumSize)
{

    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "HeapCreate";                               // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数     ::special
    HANDLE hHeap = OldHeapCreate(fIOoptions, dwInitialSize, dwMaximumSize);
    info.argNum = sprintfWithTypeEx(info.argValue, fIOoptions, dwInitialSize, dwMaximumSize, hHeap);
    // 参数名
    sprintf_s(info.argName[4], "hHeap");
    // 参数名
    sprintf_s(info.argName[1], "fIOoptions");
    sprintf_s(info.argName[2], "dwInitialSize");
    sprintf_s(info.argName[3], "dwMaximumSize");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return hHeap;
}

extern "C" __declspec(dllexport) BOOL WINAPI NewHeapDestory(
    HANDLE hHeap)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "HeapDestory";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hHeap);
    // 参数名
    sprintf_s(info.argName[1], "hHeap");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return OldHeapDestory(hHeap);
}

extern "C" __declspec(dllexport) BOOL WINAPI NewHeapFree(
    HANDLE hHeap,
    DWORD dwFlags,
    _Frees_ptr_opt_ LPVOID lpMem)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "HeapFree";                                 // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hHeap, dwFlags, lpMem);
    // 参数名
    sprintf_s(info.argName[1], "hHeap");
    sprintf_s(info.argName[2], "dwFlags");
    sprintf_s(info.argName[3], "lpMem");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return OldHeapFree(hHeap, dwFlags, lpMem);
}


// 11,12,13,14,15 注册表操作 RegCreateKeyExA RegSetValueExA RegCloseKey RegOpenKeyExA RegDeleteValueA
decltype(RegCreateKeyExA)* OldRegCreateKeyExA = RegCreateKeyExA;
decltype(RegSetValueExA)* OldRegSetValueExA = RegSetValueExA;
decltype(RegCloseKey)* OldRegCloseKey = RegCloseKey;
decltype(RegOpenKeyExA)* OldRegOpenKeyExA = RegOpenKeyExA;
decltype(RegDeleteValueA)* OldRegDeleteValueA = RegDeleteValueA;

extern "C" __declspec(dllexport) LSTATUS WINAPI NewRegCreateKeyExA(
    HKEY hKey,
    LPCSTR lpSubKey,
    DWORD Reserved,
    LPSTR lpClass,
    DWORD dwOptions,
    REGSAM samDesired,
    const LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    PHKEY phkResult,
    LPDWORD lpdwDisposition)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "RegCreateKeyExA";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
    // 参数名
    sprintf_s(info.argName[1], "hKey");
    sprintf_s(info.argName[2], "lpSubKey");
    sprintf_s(info.argName[3], "Reserved");
    sprintf_s(info.argName[4], "lpClass");
    sprintf_s(info.argName[5], "dwOptions");
    sprintf_s(info.argName[6], "samDesired");
    sprintf_s(info.argName[7], "lpSecurityAttributes");
    sprintf_s(info.argName[8], "phkResult");
    sprintf_s(info.argName[9], "lpdwDisposition");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return OldRegCreateKeyExA(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
}

extern "C" __declspec(dllexport) LSTATUS WINAPI NewRegSetValueExA(
    HKEY hKey,
    LPCSTR lpValueName,
    DWORD Reserved,
    DWORD dwType,
    const BYTE * lpData,
    DWORD cbData)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "RegSetValueExA";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hKey, lpValueName, Reserved, dwType, lpData, cbData);
    // 参数名
    sprintf_s(info.argName[1], "hKey");
    sprintf_s(info.argName[2], "lpValueName");
    sprintf_s(info.argName[3], "Reserved");
    sprintf_s(info.argName[4], "dwType");
    sprintf_s(info.argName[5], "lpData");
    sprintf_s(info.argName[6], "cbData");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
        mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
        count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
        mtx[count].unlock();
    }
    // 返回原始接口
    return OldRegSetValueExA(hKey, lpValueName, Reserved, dwType, lpData, cbData);
}

extern "C" __declspec(dllexport) LSTATUS WINAPI NewRegCloseKey(
    HKEY hKey)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "RegCloseKey";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hKey);
    // 参数名
    sprintf_s(info.argName[1], "hKey");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return OldRegCloseKey(hKey);
}

extern "C" __declspec(dllexport) LSTATUS WINAPI NewRegOpenKeyExA(
    HKEY hKey,
    LPCSTR lpSubKey,
    DWORD ulOptions,
    REGSAM samDesired,
    PHKEY phkResult)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "RegOpenKeyExA";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hKey, lpSubKey, ulOptions, samDesired, phkResult);
    // 参数名
    sprintf_s(info.argName[1], "hKey");
    sprintf_s(info.argName[2], "lpSubKey");
    sprintf_s(info.argName[3], "ulOptions");
    sprintf_s(info.argName[4], "samDesired");
    sprintf_s(info.argName[5], "phkResult");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return OldRegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult);
}

extern "C" __declspec(dllexport) LSTATUS WINAPI NewRegDeleteValueA(
    HKEY hKey,
    LPCSTR lpValueName)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "RegDeleteValueA";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hKey, lpValueName);
    // 参数名
    sprintf_s(info.argName[1], "hKey");
    sprintf_s(info.argName[2], "lpValueName");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return OldRegDeleteValueA(hKey, lpValueName);
}


// 16,17,18,19 socket操作 socket send bind connect
decltype(socket)* Oldsocket = socket;
decltype(bind)* Oldbind = bind;
decltype(send)* Oldsend = send;
decltype(connect)* Oldconnect = connect;

extern "C" __declspec(dllexport) SOCKET WINAPI Newsocket(
    int af,
    int type,
    int protocol)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "socket";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, af, type, protocol);
    // 参数名
    sprintf_s(info.argName[1], "af");
    sprintf_s(info.argName[2], "type");
    sprintf_s(info.argName[3], "protocol");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return Oldsocket(af, type, protocol);
}

extern "C" __declspec(dllexport) int WINAPI Newbind(
    SOCKET s,
    const sockaddr * name,
    int namelen)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "bind";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, s, name, namelen);
    // 参数名
    sprintf_s(info.argName[1], "s");
    sprintf_s(info.argName[2], "name");
    sprintf_s(info.argName[3], "namelen)");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return Oldbind(s, name, namelen);
}

extern "C" __declspec(dllexport) int WINAPI Newsend(
    SOCKET s,
    const char* buf,
    int len,
    int flags)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "send";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, s, buf, len, flags);
    // 参数名
    sprintf_s(info.argName[1], "s");
    sprintf_s(info.argName[2], "buf");
    sprintf_s(info.argName[3], "len");
    sprintf_s(info.argName[4], "flags)");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return Oldsend(s, buf, len, flags);
}

extern "C" __declspec(dllexport) int WINAPI Newconnect(
    SOCKET s,
    const sockaddr * name,
    int namelen)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "connect";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // IP port      ::special
    struct sockaddr_in* sock = (struct sockaddr_in*)name;
    int port = htons(sock->sin_port);
    char ip[100];
    inet_ntop(AF_INET, &sock->sin_addr, ip, sizeof(ip));
    info.argNum = sprintfWithTypeEx(info.argValue, s, name, namelen, (const char*)ip, port);
    sprintf_s(info.argName[4], "IP");
    sprintf_s(info.argName[5], "port");
    // 参数名
    sprintf_s(info.argName[1], "s");
    sprintf_s(info.argName[2], "name");
    sprintf_s(info.argName[3], "namelen");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return Oldconnect(s, name, namelen);
}


// 20,21 不知道什么操作 memcpy recv
decltype(memcpy)* Oldmemcpy = memcpy;
decltype(recv)* Oldrecv = recv;
extern "C" __declspec(dllexport) void* __cdecl Newmemcpy(
    void* _Dst,
    const void* _Src,
    size_t _Size)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "memcpy";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, _Dst, _Src, _Size);
    // 参数名
    sprintf_s(info.argName[1], "_Dst");
    sprintf_s(info.argName[2], "_Src");
    sprintf_s(info.argName[3], "_Size");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return Oldmemcpy(_Dst, _Src, _Size);
}

extern "C" __declspec(dllexport) int WINAPI Newrecv(
    SOCKET s,
    char* buf,
    int len,
    int flags)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "recv";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, s, buf, len, flags);
    // 参数名
    sprintf_s(info.argName[1], "s");
    sprintf_s(info.argName[2], "buf");
    sprintf_s(info.argName[3], "len");
    sprintf_s(info.argName[4], "flags");
    // 共享内存管理
    if (UpdateShm(shm, count) != -1) {
    mtx[count].lock();                                                  // 避免其他线程也写入同一块区域
    count = WriteShm(hSemap, shm, count, info);                         // 更新循环递增序号
    mtx[count].unlock();}
    // 返回原始接口
    return Oldrecv(s, buf, len, flags);
}


// 堆操作 HeapCreate HeapDestory
// Question: 究竟用WINAPI还是APIENTRY？？？(都一样，都是指示编译器按照API的参数入栈方式编译。看引用模式，它被define成WINAPI)
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH://加载进程时调用的代码
    {   
        //GetModuleFileNameA(0, outputStr, 256);
        //OutputDebugStringA(outputStr);
        //初始化共享内存的全局参数
        shm = InitShm(hSemap, hMap, pShm, nameSemap, nameShm);
        
        DetourRestoreAfterWith();       // Question: 这个用来干什么的？
        DisableThreadLibraryCalls(hModule);
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());

        DetourAttach(&(PVOID&)OldMessageBoxA, NewMessageBoxA);
        DetourAttach(&(PVOID&)OldMessageBoxW, NewMessageBoxW);
        DetourAttach(&(PVOID&)OldCreateFileA, NewCreateFileA);
        DetourAttach(&(PVOID&)OldWriteFile, NewWriteFile);
        //DetourAttach(&(PVOID&)OldReadFile, NewReadFile);
        DetourAttach(&(PVOID&)OldOpenFile, NewOpenFile);
        //DetourAttach(&(PVOID&)OldHeapAlloc, NewHeapAlloc);
        DetourAttach(&(PVOID&)OldHeapCreate, NewHeapCreate);
        DetourAttach(&(PVOID&)OldHeapDestory, NewHeapDestory);
        DetourAttach(&(PVOID&)OldHeapFree, NewHeapFree);
        /*DetourAttach(&(PVOID&)OldRegCreateKeyExA, NewRegCreateKeyExA);
        DetourAttach(&(PVOID&)OldRegSetValueExA, NewRegSetValueExA);
        DetourAttach(&(PVOID&)OldRegCloseKey, NewRegCloseKey);
        DetourAttach(&(PVOID&)OldRegOpenKeyExA, NewRegOpenKeyExA);
        DetourAttach(&(PVOID&)OldRegDeleteValueA, NewRegDeleteValueA);
        DetourAttach(&(PVOID&)Oldsocket, Newsocket);
        DetourAttach(&(PVOID&)Oldbind, Newbind);
        DetourAttach(&(PVOID&)Oldsend, Newsend);
        DetourAttach(&(PVOID&)Oldconnect, Newconnect);
        DetourAttach(&(PVOID&)Oldmemcpy, Newmemcpy);
        DetourAttach(&(PVOID&)Oldrecv, Newrecv);*/
        

        DetourTransactionCommit();
        break;
    }
    case DLL_THREAD_ATTACH://加载线程时
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
    {
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());

       DetourDetach(&(PVOID&)OldMessageBoxA, NewMessageBoxA);
        DetourDetach(&(PVOID&)OldMessageBoxW, NewMessageBoxW);
        DetourDetach(&(PVOID&)OldCreateFileA, NewCreateFileA);
        DetourDetach(&(PVOID&)OldWriteFile, NewWriteFile);
        //DetourDetach(&(PVOID&)OldReadFile, NewReadFile);
        DetourDetach(&(PVOID&)OldOpenFile, NewOpenFile);
        //DetourDetach(&(PVOID&)OldHeapAlloc, NewHeapAlloc);
        DetourDetach(&(PVOID&)OldHeapCreate, NewHeapCreate);
        DetourDetach(&(PVOID&)OldHeapDestory, NewHeapDestory);
        DetourDetach(&(PVOID&)OldHeapFree, NewHeapFree);
        /*DetourDetach(&(PVOID&)OldRegCreateKeyExA, NewRegCreateKeyExA);
        DetourDetach(&(PVOID&)OldRegSetValueExA, NewRegSetValueExA);
        DetourDetach(&(PVOID&)OldRegCloseKey, NewRegCloseKey);
        DetourDetach(&(PVOID&)OldRegOpenKeyExA, NewRegOpenKeyExA);
        DetourDetach(&(PVOID&)OldRegDeleteValueA, NewRegDeleteValueA);
        DetourDetach(&(PVOID&)Oldsocket, Newsocket);
        DetourDetach(&(PVOID&)Oldbind, Newbind);
        DetourDetach(&(PVOID&)Oldsend, Newsend);
        DetourDetach(&(PVOID&)Oldconnect, Newconnect);
        DetourDetach(&(PVOID&)Oldmemcpy, Newmemcpy);
        DetourDetach(&(PVOID&)Oldrecv, Newrecv);*/

        DetourTransactionCommit();

        DestoryShm(hMap, pShm);
        break;
    }
    }
    return TRUE;
 }

